package com.qiall.gateway.service.dubborpc;

import com.alibaba.fastjson.JSON;
import com.qiall.common.exception.BusinessException;
import com.qiall.common.exception.ResultCode;
import com.qiall.gateway.service.InvokeDubboService;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.utils.SimpleReferenceCache;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.service.GenericService;
import org.springframework.lang.Nullable;
import com.alibaba.dubbo.rpc.service.GenericException;
import java.util.ArrayList;
import java.util.List;

/**
 * 功能描述： 基于 Dubbo 泛化调用特性的远程调用
 *
 * @author geekziyu
 * @version 1.0.0
 */
public class DubboRpc {

    private RegistryConfig registry;

    public DubboRpc(ApplicationConfig application, RegistryConfig registry) {
        this.registry = registry;

        ApplicationModel.defaultModel().getApplicationConfigManager().setApplication(application);
    }

    public Object genericInvoke(String interfaceClass, String methodName, List<String> parameterTypes, Object[] objects) {
        return genericInvoke(interfaceClass, methodName, parameterTypes, objects, null, registry.getVersion());
    }

    private Object genericInvoke(String interfaceClass, String methodName, List<String> parameterTypes, Object[] objects, @Nullable String group, @Nullable String version) {
        ReferenceConfig<GenericService> reference = new ReferenceConfig<>();
        reference.setRegistry(registry);
        reference.setInterface(interfaceClass); // 接口名
        reference.setGeneric("true"); // 声明为泛化接口
        reference.setTimeout(30000);
        reference.setCheck(false); // 不检查状态
        if (StringUtils.isNotBlank(group)) { // NOSONAR
            reference.setGroup(group);
        }
        if (StringUtils.isNotBlank(version)) {// NOSONAR
            reference.setVersion(version);
        }
        SimpleReferenceCache cache = SimpleReferenceCache.getCache();
        GenericService genericService = cache.get(reference);
        Object respObj=null;
        try{
            respObj = genericService.$invoke(methodName, parameterTypes.toArray(new String[parameterTypes.size()]), objects);
        }
        catch (RuntimeException e){
            //这里捕获到的是dubbo 的 GenericException
            if(e instanceof GenericException){
                GenericException businessException=(GenericException)e;
              String[] errorArray=  businessException.getExceptionMessage().split("\\|");
                if (errorArray.length!= 2) {
                    throw new BusinessException(ResultCode.SYSTEM_ERROR,businessException.getExceptionMessage());
                }
               String code=errorArray[0];
               String message= errorArray[1];
                throw new BusinessException(ResultCode.ofCode(Integer.parseInt(code)),message);
             }
            throw new BusinessException(ResultCode.SYSTEM_ERROR,e.getMessage());
        }
        return respObj;
    }
}
